package com.qf.service.impl;

import com.qf.config.RedisKey;
import com.qf.dao.LiveUserRepository;
import com.qf.pojo.reqVo.LiveUserReq;
import com.qf.pojo.respVo.BaseResp;
import com.qf.pojo.vo.entity.LiveUser;
import com.qf.service.LiveUserService;
import com.qf.utils.JWTUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 陌人不故
 * @Date: 2022/10/25/17:11
 */
@Service
public class LiveUserServiceImpl implements LiveUserService {

    @Autowired
    LiveUserRepository liveUserRepository;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RedissonClient redissonClient;
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Override
    public BaseResp validataEmail(String eamil) {
        LiveUser liveUser = liveUserRepository.findByEmail(eamil);
        if (liveUser == null){
            return BaseResp.SUCCESS("邮箱可用",null,null);
        }
        return BaseResp.FAIL("邮箱已存在，请登录!");
    }

    @Override
    public BaseResp validataloginName(LiveUserReq liveUserReq) {
        LiveUser byLoginName = liveUserRepository.findByLoginName(liveUserReq.getLoginName());
        if (byLoginName == null){
            return BaseResp.SUCCESS("用户名可用",null,null);
        }
        return BaseResp.FAIL("用户名已存在，请登录!");
    }

    /**
     * 邮件发送
     * @param email
     * @return
     */
    @Override
    public BaseResp getCode(String email) {
        LiveUser byEmail = liveUserRepository.findByEmail(email);
        Boolean aBoolean = redisTemplate.hasKey(RedisKey.VALIDATA_KEY + email);
        if (aBoolean){
            // 设置验证码过期时间60s
            redisTemplate.expire(RedisKey.VALIDATA_KEY + email,60, TimeUnit.SECONDS);
            return BaseResp.FAIL("邮件已发送，请60s后再试!");
        }
        //分布式锁
        RLock lock = redissonClient.getLock("code-lock");
        boolean b = false;
        try {
            b = lock.tryLock(30, TimeUnit.SECONDS);
            if(b){
                if (byEmail != null){
                    return BaseResp.FAIL("邮箱已被注册!");
                }
                //采用rabbitMQ同步请求发送验证码
                rabbitTemplate.convertAndSend("","qflive-email-queue",email);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放锁
            boolean locked = lock.isLocked();
            if (locked){
                lock.unlock();
            }
        }
        return BaseResp.SUCCESS("发送成功!",null,null);
    }

    @Override
    public BaseResp registry(LiveUserReq liveUserReq) {
        //使用分布式锁保证在高并发下保证线程的唯一
        RLock lock = redissonClient.getLock("registry-lock");
        boolean b = false;
        try {
            b = lock.tryLock(30, TimeUnit.SECONDS);
            // 获得锁，执行下面的操作
            if (b){
                // 判断redis中是否有key
                Boolean aBoolean = redisTemplate.hasKey(RedisKey.VALIDATA_KEY + liveUserReq.getEmail());
                if (!aBoolean){
                    return BaseResp.FAIL("验证码未发送，或已过期!");
                }
                //从redis中获得验证码
                Object o = redisTemplate.opsForValue().get(RedisKey.VALIDATA_KEY + liveUserReq.getEmail());
                //比对验证码
                if (!liveUserReq.getCode().equals(o.toString())){
                    return BaseResp.FAIL("输入的验证码有误!");
                }
                LiveUser byEmail = liveUserRepository.findByEmail(liveUserReq.getEmail());
                if (byEmail != null){
                    return BaseResp.FAIL("邮箱已被注册!");
                }
                LiveUser byLoginName = liveUserRepository.findByLoginName(liveUserReq.getLoginName());
                if (byLoginName != null){
                    return BaseResp.FAIL("用户名已存在!");
                }
                //  添加用户到数据库
                LiveUser liveUser = new LiveUser();
                BeanUtils.copyProperties(liveUserReq,liveUser);
                liveUser.setStatus(1);
                //  设置注册时间
                liveUser.setCreateTime(new Date());
                liveUserRepository.saveAndFlush(liveUser);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放锁
            boolean locked = lock.isLocked();
            if (locked){
                lock.unlock();
            }
        }
        return BaseResp.SUCCESS("注册成功",null,null);
    }

    @Override
    public BaseResp login(LiveUserReq liveUserReq) {
        //判断用户是否存在
        LiveUser byLoginName = liveUserRepository.findByLoginName(liveUserReq.getLoginName());
        if (byLoginName == null){
            return BaseResp.FAIL("当前用户名不存在，请先注册!");
        }
        Boolean aBoolean = redisTemplate.hasKey(liveUserReq.getLoginName());
        if (aBoolean){
            //判断用户登录次数大于三次，设置60s的过期时间
            Object o = redisTemplate.opsForValue().get(liveUserReq.getLoginName());
            if (Integer.parseInt(o.toString())>=3){
                redisTemplate.expire(liveUserReq.getLoginName(),60,TimeUnit.SECONDS);
                return BaseResp.FAIL("当前账号登录次数过多，请60s后再试!");
            }
        }
        if (!liveUserReq.getPassword().equals(byLoginName.getLoginName())){
            //对当前的账号进行+1操作
            redisTemplate.opsForValue().increment(liveUserReq.getLoginName());
            return BaseResp.FAIL("用户密码错误，请重试!");
        }
        Map map = new HashMap<>();
        map.put("username",byLoginName.getLoginName());
        map.put("id",byLoginName.getUserId());
        String jwt = JWTUtils.signToken(map);
        // 生成token
        String token = UUID.randomUUID().toString();
        // 设置300s的过期时间，时间过后自动注销
        redisTemplate.boundValueOps(RedisKey.LOGIN_KEY + token).set(jwt,300,TimeUnit.SECONDS);
        return BaseResp.SUCCESS("登录成功",token,null);
    }

    @Override
    public BaseResp findUserByToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        Object o = redisTemplate.opsForValue().get(RedisKey.LOGIN_KEY + token);
        Map map = JWTUtils.verfiyToken(o.toString());
        if (map != null){
            int id = Integer.parseInt(map.get("id").toString());
            Optional<LiveUser> byId = liveUserRepository.findById(id);
            return BaseResp.SUCCESS("解析成功!",byId.get(),null);
        }
        return BaseResp.FAIL("请登录!");
    }


}
